/* ----------------------------------------------------------------------
 * Copyright (C) 2010-2020 ARM Limited. All rights reserved.
 *
 * $Date:         23. March 2020
 * $Revision:     V1.7.0
 *
 * Project:       CMSIS DSP Library
 * Title:         arm_linear_interp_example_f32.c
 *
 * Description:   Example code demonstrating usage of sin function
 *                and uses linear interpolation to get higher precision
 *
 * Target Processor: Cortex-M55/Cortex-M7/Cortex-M4/Cortex-M3/Cortex-M0
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in
 *     the documentation and/or other materials provided with the
 *     distribution.
 *   - Neither the name of ARM LIMITED nor the names of its contributors
 *     may be used to endorse or promote products derived from this
 *     software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * -------------------------------------------------------------------- */

/**
 * @addtogroup groupExamples
 * @{
 *
 * @defgroup LinearInterpExample Linear Interpolate Example
 *
 * <b> CMSIS DSP Software Library -- Linear Interpolate Example  </b>
 *
 * <b> Description </b>
 * This example demonstrates usage of linear interpolate modules and fast math modules.
 * Method 1 uses fast math sine function to calculate sine values using cubic interpolation and method 2 uses
 * linear interpolation function and results are compared to reference output.
 * Example shows linear interpolation function can be used to get higher precision compared to fast math sin
 * calculation.
 *
 * \par Block Diagram:
 * \par
 * \image html linearInterpExampleMethod1.gif "Method 1: Sine caluclation using fast math"
 * \par
 * \image html linearInterpExampleMethod2.gif "Method 2: Sine caluclation using interpolation function"
 *
 * \par Variables Description:
 * \par
 * \li \c testInputSin_f32         points to the input values for sine calculation
 * \li \c testRefSinOutput32_f32   points to the reference values caculated from sin() matlab function
 * \li \c testOutput               points to output buffer calculation from cubic interpolation
 * \li \c testLinIntOutput         points to output buffer calculation from linear interpolation
 * \li \c snr1                     Signal to noise ratio for reference and cubic interpolation output
 * \li \c snr2                     Signal to noise ratio for reference and linear interpolation output
 *
 * \par CMSIS DSP Software Library Functions Used:
 * \par
 * - arm_sin_f32()
 * - arm_linear_interp_f32()
 *
 * <b> Refer  </b>
 * \link arm_linear_interp_example_f32.c \endlink
 *
 * \example arm_linear_interp_example_f32.c
 *
 * @} */

#include "arm_math.h"
#include "math_helper.h"

#define SNR_THRESHOLD 90
#define TEST_LENGTH_SAMPLES 10
#define XSPACING (0.005f)

/* ----------------------------------------------------------------------
 * Test input data for F32 SIN function
 * Generated by the MATLAB rand() function
 * randn('state', 0)
 * xi = (((1/4.18318581819710)* randn(blockSize, 1) * 2* pi));
 * --------------------------------------------------------------------*/
static float32_t testInputSin_f32[TEST_LENGTH_SAMPLES] = {
    -0.649716504673081170, -2.501723745497831200, 0.188250329003310100,  0.432092748487532540, -1.722010988459680800,
    1.788766476323060600,  1.786136060975809500,  -0.056525543169408797, 0.491596272728153760, 0.262309671126153390};

/*------------------------------------------------------------------------------
 *  Reference out of SIN F32 function for Block Size = 10
 *  Calculated from sin(testInputSin_f32)
 *------------------------------------------------------------------------------*/
static float32_t testRefSinOutput32_f32[TEST_LENGTH_SAMPLES] = {
    -0.604960695383043530, -0.597090287967934840, 0.187140422442966500,  0.418772124875992690, -0.988588831792106880,
    0.976338412038794010,  0.976903856413481100,  -0.056495446835214236, 0.472033731854734240, 0.259311907228582830};

/*------------------------------------------------------------------------------
 *  Method 1: Test out Buffer Calculated from Cubic Interpolation
 *------------------------------------------------------------------------------*/
static float32_t testOutput[TEST_LENGTH_SAMPLES];

/*------------------------------------------------------------------------------
 *  Method 2: Test out buffer Calculated from Linear Interpolation
 *------------------------------------------------------------------------------*/
static float32_t testLinIntOutput[TEST_LENGTH_SAMPLES];

/*------------------------------------------------------------------------------
 *  External table used for linear interpolation
 *------------------------------------------------------------------------------*/
extern const float arm_linear_interep_table[1884];

/* ----------------------------------------------------------------------
 * Global Variables for caluclating SNR's for Method1 & Method 2
 * ------------------------------------------------------------------- */
static float32_t snr1;
static float32_t snr2;

/* ----------------------------------------------------------------------------
 * Calculation of Sine values from Cubic Interpolation and Linear interpolation
 * ---------------------------------------------------------------------------- */
int32_t arm_linear_interp_main(void) {
  uint32_t i;
  arm_status status;

  arm_linear_interp_instance_f32 S = {1884, -3.141592653589793238, XSPACING, (float*)&arm_linear_interep_table[0]};

  /*------------------------------------------------------------------------------
   *  Method 1: Test out Calculated from Cubic Interpolation
   *------------------------------------------------------------------------------*/
  for (i = 0; i < TEST_LENGTH_SAMPLES; i++) {
    testOutput[i] = arm_sin_f32(testInputSin_f32[i]);
  }

  /*------------------------------------------------------------------------------
   *  Method 2: Test out Calculated from Cubic Interpolation and Linear interpolation
   *------------------------------------------------------------------------------*/

  for (i = 0; i < TEST_LENGTH_SAMPLES; i++) {
    testLinIntOutput[i] = arm_linear_interp_f32(&S, testInputSin_f32[i]);
  }

  /*------------------------------------------------------------------------------
   *            SNR calculation for method 1
   *------------------------------------------------------------------------------*/
  snr1 = arm_snr_f32(testRefSinOutput32_f32, testOutput, 2);

  /*------------------------------------------------------------------------------
   *            SNR calculation for method 2
   *------------------------------------------------------------------------------*/
  snr2 = arm_snr_f32(testRefSinOutput32_f32, testLinIntOutput, 2);

  /*------------------------------------------------------------------------------
   *            Initialise status depending on SNR calculations
   *------------------------------------------------------------------------------*/
  status = (snr2 <= snr1) ? ARM_MATH_TEST_FAILURE : ARM_MATH_SUCCESS;

  return status;
}

/** \endlink */
